﻿using QYmall.Core.Common.Emum;
using QYmall.Core.Common.Helper;
using QYmall.Core.IServices;
using QYmall.Core.Model.Models;
using QYmall.Core.Model.OAuth.QQ;
using QYmall.Core.Model.ViewModels;
using Microsoft.AspNetCore.Http;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace QYmall.Core.Services
{
    /// <summary>
    /// QQ授权接口实现
    /// </summary>
    public class QQAuthService : IQQAuthService
    {
        private readonly IHttpContextAccessor _httpContextAccessor;
        private readonly IOAuthService _oAuthService;
        private readonly IOAuthLoginService _oAuthLoginService;
        private readonly IMemberService _menberService;
        public QQAuthService(IHttpContextAccessor httpContextAccessor, IOAuthService oAuthService,
            IOAuthLoginService oAuthLoginService, IMemberService menberService)
        {
            _httpContextAccessor = httpContextAccessor;
            _oAuthService = oAuthService;
            _oAuthLoginService = oAuthLoginService;
            _menberService = menberService;
        }

        /// <summary>
        /// OAuth2生成授权跳转链接
        /// </summary>
        public async Task<string> OAuth2UrlAsync(string? type, string? redirectUri)
        {
            //取得开放平台信息
            var model = await _oAuthService.QueryAsync<OAuths>(x => x.Provider == QQConfig.Provider && x.Type == type && x.Status == 0);
            if (model == null)
            {
                throw new ResponseException("授权平台设置有误，请联系客服");
            }
            return $"{QQConfig.OAuthEndpoint}?response_type=code&client_id={model.ClientId}&redirect_uri={redirectUri}";

        }

        /// <summary>
        /// OAuth2授权账户
        /// </summary>
        public async Task<int> OAuth2SignInAsync(string? type, string? code, string? redirectUri)
        {
            //取得开放平台信息
            var model = await _oAuthService.QueryAsync<OAuths>(x => x.Provider == QQConfig.Provider && x.Type == type && x.Status == 0);
            if (model == null)
            {
                throw new ResponseException("授权平台设置有误，请联系客服");
            }
            //第一步：通过Authorization Code获取Access Token
            var tokenUrl = $"{QQConfig.TokenEndpoint}?grant_type=authorization_code&client_id={model.ClientId}&client_secret={model.ClientSecret}&code={code}&redirect_uri={redirectUri}&fmt=json";
            var tokenResult = await RequestHelper.GetAsync(tokenUrl);
            var tokenDto = JsonHelper.ToJson<TokenResultDto>(tokenResult);
            if (tokenDto?.AccessToken == null)
            {
                var dic = JsonHelper.ToJson<Dictionary<string, string>>(tokenResult);
                throw new ResponseException($"获取AccessToken失败，错误码：{dic?["error"]}，请联系客服");
            }
            //第二步：获取用户OpenID
            var openUrl = $"{QQConfig.UserIdentityEndpoint}?access_token={tokenDto.AccessToken}&fmt=json";
            var openResult = await RequestHelper.GetAsync(openUrl);
            var openDto = JsonHelper.ToJson<OpenIdResultDto>(openResult);
            if (openDto?.OpenId == null)
            {
                var dic = JsonHelper.ToJson<Dictionary<string, string>>(openResult);
                throw new ResponseException($"获取用户OpenId失败，错误码：{dic?["error"]}，请联系客服");
            }
            //如果用户已授权，则直接返回
            var loginModel = await _oAuthLoginService.QueryAsync(x => x.Provider == QQConfig.Provider && x.OpenId == openDto.OpenId);
            if (loginModel != null)
            {
                return loginModel.UserId;
            }
            //第三步：获取用户信息
            var userUrl = $"{QQConfig.UserInfoEndpoint}?access_token={tokenDto.AccessToken}&oauth_consumer_key={model.ClientId}&openid={openDto.OpenId}";
            var userResult = await RequestHelper.GetAsync(userUrl);
            var userDto = JsonHelper.ToJson<UserInfoResultDto>(userResult);
            if (userDto?.Ret != "0")
            {
                throw new ResponseException($"获取用户信息失败，错误码：{userDto?.Ret}，错误消息：{userDto?.Msg}，请联系客服");
            }
            //第四步：新增会员
            var userName = UtilConvert.GetGuidToString();
            var memberModel = await _menberService.AddAsync(new MembersEditDto
            {
                UserName = userName,
                Password = userName,
                RealName = userDto.NickName,
                Avatar = userDto.FigureUrl2
            });
            //第五步：关联用户授权
            await _oAuthLoginService.AddAsync<OAuthLogin>(new OAuthLogin
            {
                OAuthId = model.Id,
                Provider = model.Provider,
                UserId = memberModel.UserId,
                OpenId = openDto.OpenId
            });
            return memberModel.UserId;
        }

        /// <summary>
        /// 通过JSCODE授权账户
        /// </summary>
        public async Task<int> JsCodeSignInAsync(string? type, string? code, string? realName, string? avatar)
        {
            //取得开放平台信息
            var model = await _oAuthService.QueryAsync<OAuths>(x => x.Provider == QQConfig.Provider && x.Type == type && x.Status == 0);
            if (model == null)
            {
                throw new ResponseException("授权平台设置有误，请联系客服");
            }
            //第一步：获取用户OpenID
            var openUrl = $"{QQConfig.JsCodeEndpoint}?appid={model.ClientId}&secret={model.ClientSecret}&js_code={code}&grant_type=authorization_code";
            var openResult = await RequestHelper.GetAsync(openUrl);
            var openDto = JsonHelper.ToJson<JsCodeResultDto>(openResult);
            if (openDto?.OpenId == null)
            {
                throw new ResponseException($"获取用户OpenId失败，错误码：{openDto?.ErrCode}，请联系客服");
            }
            //如果用户已授权，则直接返回
            var loginModel = await _oAuthLoginService.QueryAsync(x => x.Provider == QQConfig.Provider && x.OpenId == openDto.OpenId, WriteRoRead.Write);
            if (loginModel != null)
            {
                return loginModel.UserId;
            }
            //第二步：新增会员
            var userName = UtilConvert.GetGuidToString();
            var memberModel = await _menberService.AddAsync(new MembersEditDto
            {
                UserName = userName,
                Password = userName,
                RealName = realName,
                Avatar = avatar
            });
            //第三步：关联用户授权
            await _oAuthLoginService.AddAsync<OAuthLogin>(new OAuthLogin
            {
                OAuthId = model.Id,
                Provider = model.Provider,
                UserId = memberModel.UserId,
                OpenId = openDto.OpenId
            });
            return memberModel.UserId;
        }
    }
}
